/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package bbd.crawler.media;

import bbd.crawler.fwk.BaseFactory;
import bbd.crawler.helper.InitializeHelper;
import bbd.crawler.media.fwk.BaseURLMediaHandler;
import bbd.crawler.media.fwk.BaseURLMediaInterface;
import bbd.crawler.util.Console;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 *
 * @author Harit
 */
public class Scheduler extends BaseFactory {

    private static Scheduler instance = null;
    private static String queryString = null;
    private static String propertyFile = null;
    private static boolean schedulerRunning = false;

    private static String HTTP_URL_REGEX = null;
    private static final String REMOVE_HREF_TAG = "<a href=\"";
    private static final String REMOVE_END_QUOTE = "\"$";
    private static final String REPLACE_WITH_NOTHING = "";
    private static final String SPLIT_WITH_SPACE = " ";
    private static final String HTTP_START_TAG = "http://";
    private static final String RELATIVE_URL_START = "/";

    private static List<String> AUDIO_CONTENT_TYPE;
    private static List<String> VIDEO_CONTENT_TYPE;
    private static List<String> HTML_CONTENT_TYPE;
    private static List<String> IGNORE_DOMAINS;
    private static CopyOnWriteArraySet<String> toSearchURLs = new CopyOnWriteArraySet<String>();
    private static Set<String> searchedURLs = new HashSet<String>();
    //--------------------------------------------------------------------------
    /** Javadoc here */
    private Scheduler () {

        /* need a generic path for it */
        propertyFile = "C:\\Here We Go\\Padhayi\\projects\\Crawler\\src\\bbd\\crawler\\media\\url-params.properties";

        bundleBaseName = "bbd.crawler.media.url-map";
        basePackage    = "url.base.package";
        baseMapConfig  = "url.map.config";

        loadHashMap ();
        setConfigurations ();
        
    } // end default constructor

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public static Scheduler getInstance () {

        if ( instance == null ) {

            instance = new Scheduler ();

        }

        return instance;
        
    } // end function getInstance

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public void setQueryString ( String query ) {

        queryString = query;

    } // end function setQueryString

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public String getQueryString () {

        return queryString;

    } // end function getQueryString

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public void crawl ( String query ) {

        this.setQueryString( query );

        Iterator musicIter = new InitializeHelper().getSongURLList().iterator();

        while ( musicIter.hasNext() ) {

            String url = (String) musicIter.next();

            try {
            
                BaseURLMediaInterface handler = getHandleFor ( getMapKey( url ) );

                if ( handler != null ) {

                    handler.query(url, query);

                    scheduleURLsForCrawling ( handler.getData() );
                }

                if ( ! schedulerRunning ) {

                    schedulerOnWork ();

                    schedulerRunning = true;

                }

            } catch ( Exception e ) {

                Console.error( "Scheduler.crawl", "Java Exception - " + e.getMessage() );
            }

        }

    } // end function crawl

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public static BaseURLMediaHandler getHandleFor ( String url ) 
            throws ClassNotFoundException,
            IllegalAccessException,
            InstantiationException
    {

        if ( instance == null ) {

            instance = new Scheduler ();

        }

        return instance.getHandlerInstance ( url );
        
    } // end function getHandleFor

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public BaseURLMediaHandler getHandlerInstance ( String url )
            throws ClassNotFoundException,
            InstantiationException,
            IllegalAccessException
    {

        return ( BaseURLMediaHandler ) getInstance ( url );
        
    } // end function getHandlerInstance

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public void setConfigurations () {

        try {

            Properties property = new Properties ( );

            property.load( new FileInputStream ( propertyFile ) );

            HTTP_URL_REGEX = property.getProperty( "url.http.regex" );
            AUDIO_CONTENT_TYPE = Arrays.asList( property.getProperty( "url.audio.content" ).split("#") );
            VIDEO_CONTENT_TYPE = Arrays.asList( property.getProperty( "url.video.content" ).split("#") );
            HTML_CONTENT_TYPE = Arrays.asList( property.getProperty( "url.html.content" ).split("#") );
            IGNORE_DOMAINS = Arrays.asList( property.getProperty( "http.ignore.domain" ) );

        } catch ( Exception e ) {

            Console.error( "Scheduler.setConfigurations", "Java Exception - " + e.getMessage() );
        }
        
    } // end function setConfigurations

    //--------------------------------------------------------------------------
    /** Javadoc here */
    private void scheduleURLsForCrawling ( Object data ) {

        if ( data == null ) return;

        HashSet<String> freshLinks = ( HashSet<String> ) data;

        Iterator iter = freshLinks.iterator();

        while ( iter.hasNext() ) {

            String urlEntry = iter.next().toString();

            if ( isNewLinkFound ( urlEntry ) ) {

                toSearchURLs.add( urlEntry );
            }

        }

    } // end function scheduleURLsForCrawling

    //--------------------------------------------------------------------------
    /** Javadoc here */
    private boolean isNewLinkFound ( String urlString ) {

        boolean returnValue = false;

        if ( ! urlFoundInQueue ( urlString ) ) {

            if ( ! urlFoundInIgnoreDomainList ( urlString ) ) {

                returnValue = true;
            }
            
        }

        return returnValue;
        
    } // end function isNewLinkFound

    //--------------------------------------------------------------------------
    /** Javadoc here */
    private boolean urlFoundInQueue ( String urlString ) {

        if ( ( toSearchURLs.isEmpty() ) && ( searchedURLs.isEmpty() ) ) {

            return false;
        }

        if ( ( toSearchURLs.contains( urlString ) ) ||
                            ( searchedURLs.contains( urlString ) ) )
        {

            return true;
        }
        
        return false;
        
    } // end function urlFoundInQueue

    //--------------------------------------------------------------------------
    /** Javadoc here */
    private boolean urlFoundInIgnoreDomainList ( String urlString ) {

        /**
         *  This function ignores those
         *  domains which might make crawler
         *  run in cycle.
         */
        
        Iterator iterator = IGNORE_DOMAINS.iterator();

        if ( urlString.contains( (CharSequence) iterator.next() ) ) {

            System.out.println("Ignoring : " + urlString);
            return true;
        }

        return false;

    } // end function urlFoundInIgnoreDomainList

    //--------------------------------------------------------------------------
    /** Javadic here */
    private void schedulerOnWork () {

    } // end fucntion schedulerOnWork


} // end class scheduler
